using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;

namespace EventAbstractionAPI.ApplicationObjectModel
{
    public class XPathNav : XPathNavigator
    {
        #region Constructor

        public XPathNav(myTreeNodeClass tnc)
        {
            _currentNode = tnc;
            //Console.WriteLine("Root Set: " + currentNode.name);
        }

        #endregion

        #region XPathnavigator Methods

        // The location from which the node was loaded, or String.Empty if there is no value.
        public override string BaseURI
        {
            get
            {
                //Console.WriteLine("Base URI Called: " + currentNode.name); 
                return string.Empty;
            }

        }

        // A new XPathNavigator positioned at the same node as this XPathNavigator.
        public override XPathNavigator Clone()
        {
            XPathNavigator nav = (XPathNavigator)this.MemberwiseClone();
            //Console.WriteLine("Clone: " + currentNode.name);
            return nav;
        }

        // Returns true if the current node is an empty element; otherwise, false.
        public override bool IsEmptyElement
        {
            get
            {
                //Console.WriteLine("IsEmptyElement: " + currentNode.name);
                return _currentNode == null;
            }
        }

        //Returns true if the two XPathNavigator objects have the same position; otherwise, false.
        public override bool IsSamePosition(XPathNavigator other)
        {
            bool a = (this._currentNode.name == other.Value);
            //bool b = (other.IsSamePosition(this));
            //check to see if another naviagator is in the same position.
            return a;
            //return (other.ComparePosition(this) == XmlNodeOrder.Same);
            return false;
        }

        //The local name returned depends on the XPathNodeType of the current node
        //----------------------------------------------------------------------
        //XPathNodeType         | Return value
        //-----------------------------------------------------------------------
        //Element               | The local name of the element
        //Attribute             | The local name of the attribute
        //Namespace             | The prefix associated with the namespace URI
        //ProcessingInstruction | The target of the processing instruction.
        //All other node types  | String.Empty
        //-----------------------------------------------------------------------
        public override string LocalName
        {

            get
            {
                String returnValue;
                switch (_currentNode.NodeType)
                {
                    case XPathNodeType.Element:
                        returnValue = _currentNode.name;
                        break;
                    case XPathNodeType.Attribute:
                        returnValue = _currentNode.name;
                        break;
                    case XPathNodeType.Namespace:
                        //returnValue = "Not yet implemented";
                        throw new Exception("The method or operation is not implemented.");
                        break;
                    case XPathNodeType.ProcessingInstruction:
                        throw new Exception("The method or operation is not implemented.");
                        //returnValue =
                        break;
                    default:
                        returnValue = String.Empty;
                        break;
                }
                //Console.WriteLine("LocalName: " + currentNode.name);
                return returnValue;
            }
        }

        //Returns true if the XPathNavigator is successful moving to the same position as the specified
        //XPathNavigator; otherwise, false. If false, the position of the XPathNavigator is unchanged.
        public override bool MoveTo(XPathNavigator other)
        {
            //this.MoveToRoot();
            //throw new Exception("The method or operation is not implemented.");
            //move to the position of other
            //searchChildren(currentNode);

            //this.MoveToRoot();
            if (other.IsSamePosition(this))
            {
                return true;
            }
            while (this.MoveToNext())
            {
                if (other.IsSamePosition(this))
                {
                    return true;
                }
            }
            //Console.WriteLine("MoveTo: " + currentNode.name);
            //check if the function worked.
            return other.IsSamePosition(this);
        }

        public override bool MoveToFirstAttribute()
        {
            _previousNode = _currentNode;
            if (!MoveToFirstChild())
            {
                _currentNode = _previousNode;
                return false;
            }
            while (_currentNode.NodeType != XPathNodeType.Attribute)
            {
                if (MoveToNext())
                {

                }
                else
                {
                    _currentNode = _previousNode;
                    return false;
                }
            }
            return true;
        }

        public override bool MoveToFirstChild()
        {
            if (_currentNode.Children.Count > 0)
            {
                //Console.WriteLine("MoveToFirstChild(True): " + currentNode.name);
                _previousNode = _currentNode;
                _currentNode = _currentNode.FirstChild;
                return true;
            }
            else
            {
                //Console.WriteLine("MoveToFirstChild(False): " + currentNode.name);
                return false;
            }
        }

        public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override bool MoveToId(string id)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        //move to next sibbling
        public override bool MoveToNext()
        {
            //#################################################################
            try //the form is not gonna have any siblings in this example
            {
                LinkedList<myTreeNodeClass>.Enumerator enumeratorInst = _currentNode.Parent.Children.GetEnumerator();
                while (enumeratorInst.MoveNext())
                {
                    if (_currentNode == enumeratorInst.Current && enumeratorInst.MoveNext())
                    {
                        //Console.WriteLine("MoveToNext(True): " + currentNode.name);
                        _previousNode = _currentNode;
                        _currentNode = enumeratorInst.Current;
                        return true;
                    }
                }
            }
            catch (Exception)
            {

            }
            //Console.WriteLine("MoveToNext(False): " + currentNode.name);
            return false;
            //throw new Exception("The method or operation is not implemented.");
        }

        public override bool MoveToNextAttribute()
        {
            _previousNode = _currentNode;
            if (!MoveToNext())
            {
                _currentNode = _previousNode;
                return false;
            }
            while (_currentNode.NodeType != XPathNodeType.Attribute)
            {
                if (MoveToNext())
                {

                }
                else
                {
                    _currentNode = _previousNode;
                    return false;
                }
            }
            return true;
        }

        public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override bool MoveToParent()
        {
            if (_currentNode.Parent != null)
            {
                //Console.WriteLine("MoveToParent(True): " + currentNode.name);
                _previousNode = _currentNode;
                _currentNode = _currentNode.Parent;
                return true;
            }
            else
            {
                //Console.WriteLine("MoveToParent(False): " + currentNode.name);
                return false;
            }
        }

        public override bool MoveToPrevious()
        {
            //return (currentNode.PrevNode() != null);
            throw new Exception("The method or operation is not implemented.");
        }

        //The Name returned depends on the XPathNodeType of the current node.
        //For example, the name for the <bk:book> element is bk:book.
        public override string Name
        {
            get
            {
                String returnValue;
                switch (_currentNode.NodeType)
                {
                    case XPathNodeType.Element:
                        returnValue = _currentNode.name;
                        break;
                    case XPathNodeType.Attribute:
                        returnValue = _currentNode.name;
                        break;
                    case XPathNodeType.Namespace:
                        //returnValue = "Not yet implemented";
                        throw new Exception("The method or operation is not implemented.");
                        break;
                    case XPathNodeType.ProcessingInstruction:
                        throw new Exception("The method or operation is not implemented.");
                        //returnValue =
                        break;
                    default:
                        returnValue = String.Empty;
                        break;
                }
                //Console.WriteLine("Name{get}: " + currentNode.name);
                return returnValue;
            }
        }

        public override System.Xml.XmlNameTable NameTable
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        //The namespace URI of the current node or an empty string if the current node does not have one.
        //For example NamespaceURI returns urn:samples for the node <bk:book xmlns:bk='urn:samples'>.
        public override string NamespaceURI
        {
            get
            {
                //Console.WriteLine("NameSpaceURI{get}: " + currentNode.name);
                return String.Empty;
            }
        }

        // One of the XPathNodeType values representing the current node.
        public override XPathNodeType NodeType
        {
            get
            {
                //Console.WriteLine("Nodetype{get}: " + currentNode.name);
                return _currentNode.NodeType;
            }
        }

        public override string Prefix
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        public override String Value
        {
            get
            {
                //Console.WriteLine("Value{get}: " + currentNode.name);
                string output;
                try
                {
                    return _currentNode.value.ToString();
                }
                catch (Exception)
                {
                    return _currentNode.name;
                }

            }
        }

        public Object getCurrentNode()
        {
            return _currentNode;
        }

        #endregion

        #region Member Variables

        private myTreeNodeClass _previousNode;
        private myTreeNodeClass _currentNode;

        #endregion
    }
}
